// 参考链接： https://juejin.cn/post/7136080358688161828?searchId=2024051413062559C50576401196612D3C
const events = {
  start: "mousedown",
  move: "mousemove",
  stop: "mouseup",
};

//拖拽的节流方法
const throttle2 = (fn, delay) => {
  let valid = true;
  return (...args) => {
    if (!valid) {
      return;
    }
    valid = false;
    setTimeout(() => {
      fn(...args);
      valid = true;
    }, delay);
  };
};

const noop = () => {};

//对table组件进行重构的核心方法组件
const DragHandler = {
  name: "nio-drag-handler",
  //获取混入的方法（重新设置表头宽度）
  inject: {
    onResizeColumn: {
      default: noop
    },
    columns: {
      default: []
    },
    getDomCols: {
      default: noop
    }
  },
  props: {
    column: { type: Object, required: true },
    minWidth: { type: Number, required: true }
  },

  data() {
    return {
      dragging: false,
      thWidth: 0,// 列头的宽度，用于计算
      startX: 0,
      moveEvent: {
        remove: noop
      },
      stopEvent: {
        remove: noop
      }
    };
  },
  //销毁监听
  beforeDestroy() {
    this.removeEvents();
  },
  methods: {
    //鼠标开始拖拽
    handleMouseDown(e) {
      e.stopPropagation();
      e.preventDefault();
      this.handleStart(e);
    },

    handleStart(e) {
      this.dragging = true;
      this.removeEvents();
      this.thWidth = this.$el.parentNode.getBoundingClientRect().width;
      if (e instanceof MouseEvent && e.which !== 1) {
        return;
      }
      e.preventDefault();
      if (e.stopPropagation) e.stopPropagation();
      this.startX = e.pageX;
      this.moveEvent = addEventListenerWrap(document.documentElement, events.move, this.handleMove);
      this.stopEvent = addEventListenerWrap(document.documentElement, events.stop, this.handleStop);
    },

    handleMove(e) {
      this.updateWidth(e);
    },
    handleStop(e) {
      this.dragging = false;
      this.updateWidth(e);
      this.removeEvents();
    },

    updateWidth(e) {
      let pageX = e.pageX;
      const tmpDeltaX = this.startX - pageX;
      if(tmpDeltaX == 0) {
        return
      }
      let w = Math.max(this.thWidth - tmpDeltaX, this.minWidth);
      w = Math.min(w, Infinity);
      this.onResizeColumn(w, this.column, this.getDomCols());
    },

    removeEvents() {
      this.moveEvent.remove();
      this.stopEvent.remove();
    }
  },
  //渲染div 绑定拖拽
  render(h) {
    const line = h("div", { class: "nio-drag-handler-line" }, []);
    return h("div", { class: "nio-drag-handler", on: { mousedown: this.handleMouseDown } }, [line]);
  }
};

//监听鼠标移动的方法
function addEventListenerWrap(target, eventType, cb) {
  if (target && target.addEventListener) {
    target.addEventListener(eventType, cb);
  }

  return {
    remove: () => {
      if (target && target.removeEventListener) {
        target.removeEventListener(eventType, cb);
      }
    },
  };
}

//重构table组件的核心渲染函数
export default function ResizeHeader(compIns) {
  return function _resizeHeader(h, props, children) {
    const { key, column, ...restProps } = props;
    let content = [].concat(children);
    if (column?.resizable) {
      if(column.size !== column.colIndex+1 || (column.size === column.colIndex+1 && ('width' in column)) ) {
        const handlerVNode = h(DragHandler, {
          props: {
            width: column.width || 0,
            minWidth: Math.min(column.width || 0, 100),
            column: column
          }
        }, []);
        content = content.concat(
          handlerVNode
        );
      }
    }
  
    return h("th", {
      key,
      props: { column },
      ...Object.assign({}, restProps, { class: (restProps.class || "") + " nio-header-th" })
    }, content);
  };
};


//在table组件中混入的一个方法 provide => onResizeColumn 
//目的是在table重写中（DragHandler方法）
//可以用到构造的onResizeColumn方法（重新设置表头的宽度）
export const ResizeColumnProvide = {
  provide() {
    return {
      onResizeColumn: this.onResizeColumn,
      columns: this[this.columnsKey],
      getDomCols: this.getDomCols
    };
  },

  data() {
    const onResizeColumn = throttle2(this._resizeColumn, 30);
    return {
      resizeableTableRef: 'resizeableTableRef',
      columnsKey: "columns", //这个属性是table组件表头的集合名称 :columns="columns"
      moving:false, //这个属性是为了在拖拽时 阻止表头触发排序的功能
      onResizeColumn,
      cols: [],
    };
  },
  mounted() {
    const antTable = this.$refs[this.resizeableTableRef];
    const colGroup = antTable.$el.querySelector("colgroup");
    this.cols = colGroup.children;
    [...this.cols].forEach((col, index) => {
      if(index !== this.cols.length - 1 && !this[this.columnsKey][index].width) {
        col.style.width = getComputedStyle(col).width;
      }
    });
    const endCol = this.cols[this.cols.length - 1];
    const col = document.createElement("col");
    // 最后一列没设置宽度
    if(isNaN(parseFloat(endCol.style.width))) {
      col.style.width = "0";
    }else {
      col.style.width = "auto";
    }
    colGroup.appendChild(col);
  },
  methods: {
    _resizeColumn(w, column, cols) {
      const columns = this[this.columnsKey];
      this.moving = true
      let time = setTimeout(() => {
        this.moving = false
        clearTimeout(time)
      }, 200);
      //在拖拽时找到对应表头 重新设置表头的宽度   
      //这就是为什么表头column要绑定customHeaderCell的原因           
      const matchedIndex = columns.findIndex(item => item.key === column.key);
      columns[matchedIndex].width = w;
      this.$nextTick(() => {
        cols[matchedIndex].style.width = w+'px';
        cols[matchedIndex].style.minWidth = w+'px';
      });
    },
    getDomCols() {
      return this.cols;
    }
  }
};

export function customHeaderCell(column) {
  return Object.assign({
    column: column
  });
};